using System;
using System.Collections.Generic;
using System.Configuration;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Web;

namespace XZ.Logistics.WebShop
{
    public static class WebShop
    {
        public readonly static WebShopSection Settings = (WebShopSection)WebConfigurationManager.GetSection("system.web/webshop");
        private static WebShopProvider _provider = null;
        private static WebShopProviderCollection _providers = null;
        private static object _lock = new object();

        public static WebShopProvider Provider
        {
            get { return _provider; }
        }

        public static WebShopProviderCollection Providers
        {
            get { return _providers; }
        }

        // methods that work with departments
        public static List<Category> GetCategories()
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetCategories();
        }
        public static Category GetCategoryById(Guid categoryId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetCategoryById(categoryId);
        }
        public static bool DeleteCategory(Guid categoryId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DeleteCategory(categoryId);
        }
        public static bool UpdateCategory(Category category)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.UpdateCategory(category);
        }
        public static Guid InsertCategory(Category category)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertCategory(category);
        }

        // methods that work with order statuses
        public static List<OrderStatus> GetOrderStatuses()
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrderStatuses();
        }
        public static OrderStatus GetOrderStatusById(int orderStatusId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrderStatusById(orderStatusId);
        }
        public static bool DeleteOrderStatus(int orderStatusId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DeleteOrderStatus(orderStatusId);
        }
        public static bool UpdateOrderStatus(OrderStatus orderStatus)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.UpdateOrderStatus(orderStatus);
        }
        public static int InsertOrderStatus(OrderStatus orderStatus)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertOrderStatus(orderStatus);
        }

        // methods that work with shipping methods
        public static List<ShippingMethod> GetShippingMethods()
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetShippingMethods();
        }
        public static ShippingMethod GetShippingMethodById(Guid shippingMethodId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetShippingMethodById(shippingMethodId);
        }
        public static bool DeleteShippingMethod(Guid shippingMethodId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DeleteShippingMethod(shippingMethodId);
        }
        public static bool UpdateShippingMethod(ShippingMethod shippingMethod)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.UpdateShippingMethod(shippingMethod);
        }
        public static Guid InsertShippingMethod(ShippingMethod shippingMethod)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertShippingMethod(shippingMethod);
        }

        // methods that work with products
        public static List<Product> GetProducts(string sortExpression, int pageIndex, int pageSize)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProducts(sortExpression, pageIndex, pageSize);
        }
        public static List<Product> GetProducts(Guid categoryId, string sortExpression, int pageIndex, int pageSize)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProducts(categoryId, sortExpression, pageIndex, pageSize);
        }
        public static int GetProductCount()
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProductCount();
        }
        public static int GetProductCount(Guid categoryId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProductCount(categoryId);
        }
        public static Product GetProductById(Guid productId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProductById(productId);
        }
        public static bool DeleteProduct(Guid productId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DeleteProduct(productId);
        }
        public static bool UpdateProduct(Product product)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.UpdateProduct(product);
        }
        public static Guid InsertProduct(Product product)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertProduct(product);
        }
        public static bool RateProduct(Guid productId, int rating)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.RateProduct(productId, rating);
        }
        public static bool DecrementProductUnitsInStock(Guid productId, int quantity)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DecrementProductUnitsInStock(productId, quantity);
        }
        public static string GetProductDescription(Guid productId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetProductDescription(productId);
        }

        // methods that work with orders
        public static List<Order> GetOrders(int statusId, DateTime fromDate, DateTime toDate)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrders(statusId, fromDate, toDate);
        }
        public static List<Order> GetOrders(string addedBy)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrders(addedBy);
        }
        public static Order GetOrderById(Guid orderId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrderById(orderId);
        }
        public static bool DeleteOrder(Guid orderId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.DeleteOrder(orderId);
        }
        public static Guid InsertOrder(Order order)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertOrder(order);
        }
        public static bool UpdateOrder(Order order)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.UpdateOrder(order);
        }

        // methods that work with order items
        public static List<OrderItem> GetOrderItems(Guid orderId)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.GetOrderItems(orderId);
        }
        public static Guid InsertOrderItem(OrderItem orderItem)
        {
            // Make sure a provider is loaded
            LoadProviders();

            // Delegate to the provider
            return _provider.InsertOrderItem(orderItem);
        }

        private static void LoadProviders()
        {
            // Avoid claiming lock if providers are already loaded
            if (_provider == null)
            {
                lock (_lock)
                {
                    // Do this again to make sure _provider is still null
                    if (_provider == null)
                    {
                        // Get a reference to the <imageService> section
                        //ShopSection section = (ShopSection)WebConfigurationManager.GetSection("system.web/webshop");

                        // Load registered providers and point _provider
                        // to the default provider
                        _providers = new WebShopProviderCollection();
                        //ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(ShopProvider));
                        ProvidersHelper.InstantiateProviders(Settings.Providers, _providers, typeof(WebShopProvider));
                        _provider = _providers[Settings.DefaultProvider];

                        if (_provider == null)
                            throw new ProviderException("Unable to load default ShopProvider");
                    }
                }
            }
        }
    }
}